//
//  XIGeometry.h
//  XIEngine
//
//  Created by Bazsi on 12.06.09.
//  Copyright 2009 Universität Basel. All rights reserved.
//

#ifndef XIGeometry_h
#define XIGeometry_h

#import "XIEngine.h"

#pragma mark Structs

typedef struct XILine {
    float m;	// slope
    float b;	// y-intersept
} XILine;

typedef struct XILineSegment {
    CGPoint a; // point 1 
	CGPoint b; // point 2
} XILineSegment;

typedef struct XICircle {
    CGPoint c;	// center
    float r;	// radius
} XICircle;

typedef struct XIPathNode {
    CGPoint p;	// position
	float r;	// radius
	id *properties;	// optional pointer to properties
} XIPathNode;

typedef struct XIPathEntry {
    struct XIPathEntry *next;	// Pointer to next node in path.
	struct XIPathEntry *prev;	// Pointer to previous node in path.
	XIPathNode node;			// Value of the entry.
} XIPathEntry;

typedef struct XIPath {
    XIPathEntry *head;	// First node of path.
	XIPathEntry *tail;	// Last node of path.
	id *properties;		// Optional pointer to properties.
} XIPath;


#pragma mark -
#pragma mark Constants
/** Declare of extern constants. **/

XIExtern const XILine XILineZero;	// A line with equation y=0 (m=0, b=0). It equals to XILineXAxis.
XIExtern const XILine XILineXAxis; // The x-axis: y=0 (m=0, b=0).
XIExtern const XILine XILineYAxis; // The y-axis: x=0 (m=INFINITY, b=0).

XIExtern const XILineSegment XILineSegmentZero; // Both points of the segment are the origin.

XIExtern const XICircle XICircleZero; // A circle at (0,0) with radius=0.
XIExtern const XICircle XICircleUnit; // A circle at (0,0) with radius=1.

#pragma mark -
#pragma mark Creator functions
/** Definitions of creator functions. **/

XIExtern XILine XILineMake(float m, float b);						      // Creates a line with slope m and y-intercept=b.
XIExtern XILine XILineThroughPoints(CGPoint point1, CGPoint point2);	  // Creates a line that goes through the 2 passed points.
XIExtern XILine XILineThroughPointWithSlope(CGPoint point, float slope); // Create a line that goes through the point with given slope.

XIExtern XILineSegment XILineSegmentMake(CGPoint point1, CGPoint point2);

XIExtern XICircle XICircleMake(CGPoint c, float r); // Creates a circle with center c and radius r.
XIExtern XICircle XICircleThroughPoints(CGPoint point1, CGPoint point2, CGPoint point3); // Circle that goes through 3 given points.

#pragma mark -
#pragma mark Tests

XIExtern BOOL XIPointExists(CGPoint point);	// This can be used to test if the result of a calculation is a valid point (not infinity).
XIExtern BOOL XILineExists(XILine line);		// This can be used to test if the result of a calculation is a valid line (not infinity).
XIExtern BOOL XICircleExists(XICircle circle); // This can be used to test if the result of a calculation is a valid circle (not infinity).
XIExtern BOOL XILineSegmentExists(XILineSegment segment);

#pragma mark -
#pragma mark Points

XIExtern CGPoint XIPointBetweenPoints(CGPoint point1, CGPoint point2);  // Returns the point that's exactly between the 2 points. 
XIExtern float XIDistanceBetweenPoints(CGPoint point1, CGPoint point2); // Calculates the distance of 2 points.

#pragma mark -
#pragma mark Lines

XIExtern BOOL XILineIsParallelToLine(XILine line1, XILine line2);	 // Tests if 2 lines are parallel to eachother.
XIExtern BOOL XILineIsOrthogonalToLine(XILine line1, XILine line2); // Tests if 2 lines are orthogonal.
XIExtern BOOL XILineIntersectsLine(XILine line1, XILine line2);	 // Tests if the 2 lines intersets eachother (=are not parallel).
XIExtern BOOL XILineIsTangentOnCircle(XILine line, XICircle circle);// Tests if the line is a tangent on the circle.
XIExtern BOOL XILineEqualsToLine(XILine line1, XILine line2);		 // Tests if two lines are the same.
XIExtern BOOL XILineContainsPoint(XILine line, CGPoint point);		 // Tests if the line contains the passed point.
XIExtern CGPoint XILineIntersection(XILine line1, XILine line2);	 // Calculates the intersection of 2 lines. INFINITY, if lines parallel.	
XIExtern CGPoint XILineClosestPointToPoint(XILine line, CGPoint point); // Returns the point on the line that is closest to the point.	
XIExtern float XILineAngle(XILine line);							 // Angle between the line and the x-axis in deg.
XIExtern float XILineAngleWithLine(XILine line1, XILine line2);	 // Angle between 2 lines in deg.
XIExtern XILine XILineParallelToLineThroughPoint(XILine line, CGPoint point);   // Returns the line that is parallel to the line and goes through the passed point.
XIExtern XILine XILineOrthogonalToLineThroughPoint(XILine line, CGPoint point); // Returns the line that is orthogonal to the line and goes through the passed point.

#pragma mark -
#pragma mark Line segments

XIExtern BOOL XILineSegmentContainsPoint(XILineSegment segment, CGPoint point);
XIExtern CGPoint XILineSegmentClosestPointToPoint(XILineSegment segment, CGPoint point);

#pragma mark -
#pragma mark Circles

XIExtern BOOL XICircleEqualsCircle(XICircle circle1, XICircle circle2);
XIExtern BOOL XICircleAreaContainsPoint(XICircle circle, CGPoint point);
XIExtern BOOL XICircleEdgeContainsPoint(XICircle circle, CGPoint point);
XIExtern BOOL XICircleContainsPoint(XICircle circle, CGPoint point);
XIExtern int XICircleIntersection(XICircle circle1, XICircle circle2, CGPoint *intersections);
XIExtern int XICircleIntersectionWithLine(XICircle circle, XILine line, CGPoint *intersections);
XIExtern int XICircleTangentThroughPoint(XICircle circle, CGPoint point, XILine *tangents);
XIExtern BOOL XICircleContainsCircle(XICircle circle1, XICircle circle2);
XIExtern float XICircleShortestDistanceToLine(XICircle circle, XILine line);

#pragma mark -
#pragma mark Paths

XIExtern XIPathNode XIPathNodeMake(CGPoint position, id *properties);
XIExtern XIPath XIPathMake();
XIExtern BOOL XIPathPush(XIPath *path, XIPathNode node);
XIExtern BOOL XIPathPop(XIPath* path, XIPathNode* node);
XIExtern BOOL XIPathIsClosed(XIPath path);
XIExtern int XIPathCount(XIPath path);
XIExtern BOOL XIPathContainsPoint(XIPath path, CGPoint point);
XIExtern CGPoint XIPathClosestPoint(XIPath path, CGPoint point);
XIExtern CGPoint XIPathTravelFromPoint(XIPath path, CGPoint point, float length);

#endif